<template>
  <el-card class="categories-page">
    <!-- 工具栏 -->
    <div class="toolbar">
      <el-input
        v-model="filters.keyword"
        placeholder="分类名称"
        clearable
        @clear="handleSearch"
        @keyup.enter="handleSearch"
        size="small"
        class="toolbar-item"
      >
        <template #prefix
          ><el-icon><Search /></el-icon
        ></template>
      </el-input>
      <el-select
        v-model="filters.status"
        placeholder="状态"
        clearable
        @change="handleSearch"
        size="small"
        class="toolbar-item"
        style="width: 120px"
      >
        <el-option label="启用" :value="1" />
        <el-option label="禁用" :value="0" />
      </el-select>
      <el-button type="primary" size="small" @click="openDialog()">
        新增分类
      </el-button>
      <el-button
        type="danger"
        size="small"
        :disabled="!multiple.length"
        @click="handleBatchDelete"
      >
        批量删除
      </el-button>
      <el-button size="small" @click="downloadTemplate">下载模板</el-button>
      <el-upload
        :before-upload="handleImport"
        :show-file-list="false"
        size="small"
      >
        <el-button>导入</el-button>
      </el-upload>
      <el-button size="small" @click="handleExport">导出</el-button>
    </div>

    <!-- 表格 -->
    <el-table
      v-loading="loading"
      :data="list"
      stripe
      @selection-change="multiple = $event"
      style="width: 100%"
    >
      <el-table-column type="selection" width="50" />
      <el-table-column prop="id" label="ID" width="70" align="center" />
      <el-table-column label="图标" width="80" align="center">
        <template #default="{ row }">
          <el-image
            v-if="row.iconUrl"
            :src="row.iconUrl"
            style="width: 40px; height: 40px; border-radius: 4px;"
            fit="cover"
            :preview-src-list="[row.iconUrl]"
          />
          <el-icon v-else style="font-size: 24px; color: #ccc;">
            <Picture />
          </el-icon>
        </template>
      </el-table-column>
      <el-table-column prop="name" label="名称" min-width="120" />
      <el-table-column prop="parentName" label="父分类" min-width="100" />
      <el-table-column prop="description" label="描述" min-width="150" />
      <el-table-column label="排序" width="150" align="center">
        <template #default="{ row }">
          <el-input-number
            v-model="row.sort"
            :min="0"
            size="small"
            @change="onChangeSort(row)"
          />
        </template>
      </el-table-column>
      <el-table-column label="状态" width="140" align="center">
        <template #default="{ row }">
          <el-switch
            v-model="row.status"
            :active-value="1"
            :inactive-value="0"
            active-text="启用"
            inactive-text="禁用"
            size="small"
            @change="onChangeStatus(row)"
          />
        </template>
      </el-table-column>
      <el-table-column label="操作" width="160" align="center" fixed="right">
        <template #default="{ row }">
          <div class="action-btns">
            <el-button
              type="primary"
              :icon="Edit"
              circle
              @click="openDialog(row)"
            />
            <el-button
              type="danger"
              :icon="Delete"
              circle
              @click="handleDelete(row.id)"
            />
          </div>
        </template>
      </el-table-column>
    </el-table>

    <!-- 分页 -->
    <div class="pagination">
      <el-pagination
        background
        layout="prev, pager, next, jumper, sizes, total"
        :current-page="pageNum"
        :page-size="pageSize"
        :page-sizes="[10, 20, 50]"
        :total="total"
        @current-change="onPageChange"
        @size-change="onSizeChange"
      />
    </div>

    <!-- 新增/编辑 弹窗 -->
    <el-dialog :title="dialogTitle" v-model="dialogVisible" width="500px">
      <el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
        <el-form-item label="父分类" prop="parentId">
          <el-tree-select
            v-model="form.parentId"
            :data="treeData"
            placeholder="选择父分类"
            clearable
            size="small"
          />
        </el-form-item>
        <el-form-item label="名称" prop="name">
          <el-input v-model="form.name" autocomplete="off" />
        </el-form-item>
        <el-form-item label="图标" prop="iconUrl">
          <ImageUploadCropper
            v-model:imageUrl="form.iconUrl"
            aspect-ratio="1:1"
            hint="建议尺寸: 80x80px, 支持 JPG、PNG 格式，将进行裁剪"
          />
        </el-form-item>
        <el-form-item label="描述" prop="description">
          <el-input v-model="form.description" autocomplete="off" />
        </el-form-item>
        <el-form-item label="排序" prop="sort">
          <el-input-number v-model="form.sort" :min="0" size="small" />
        </el-form-item>
        <el-form-item label="状态" prop="status">
          <el-switch
            v-model="form.status"
            :active-value="1"
            :inactive-value="0"
            active-text="启用"
            inactive-text="禁用"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" :loading="saving" @click="submitForm">
          确定
        </el-button>
      </template>
    </el-dialog>
  </el-card>
</template>
  
<script setup>
import { ref, reactive, onMounted } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import {
  pageCategories,
  getCategoryTree,
  addCategory,
  updateCategory,
  deleteCategory,
  updateCategoryStatus,
  updateCategorySort,
  exportCategories,
  downloadCategoryTemplate,
  importCategories,
} from "@/api/categories";
import { Delete, Search, Edit, Picture } from "@element-plus/icons-vue";
import { useTokenStore } from "@/stores/useTokenStore";
import ImageUploadCropper from "@/components/ImageUploadCropper.vue";

const filters = reactive({ keyword: "", status: null });
const loading = ref(false);
const list = ref([]);
const total = ref(0);
const pageNum = ref(1);
const pageSize = ref(10);
const multiple = ref([]);

// 弹窗 & 表单
const dialogVisible = ref(false);
const isCreate = ref(true);
const dialogTitle = ref("新增分类");
const form = reactive({
  id: null,
  parentId: null,
  name: "",
  description: "",
  sort: 0,
  status: 1,
  iconUrl: "",
});
const formRef = ref(null);
const saving = ref(false);

// 父分类下拉树
const treeData = ref([]);

// 校验规则
const rules = {
  name: [{ required: true, message: "请输入分类名称", trigger: "blur" }],
};

// 拉数据
async function fetchList() {
  loading.value = true;
  try {
    const res = await pageCategories({
      pageNum: pageNum.value,
      pageSize: pageSize.value,
      keyword: filters.keyword,
      status: filters.status,
    });
    list.value = res.data.items;
    total.value = res.data.total;
  } finally {
    loading.value = false;
  }
}

// 加载父分类树
async function loadTree() {
  const res = await getCategoryTree();
  
  treeData.value = res.data.map((c) => ({
    value: c.id,
    label: c.name,
    children: c.children?.map((ch) => ({
      value: ch.id,
      label: ch.name,
    })),
  }));
}

// 分页回调
function onPageChange(p) {
  pageNum.value = p;
  fetchList();
}
function onSizeChange(s) {
  pageSize.value = s;
  pageNum.value = 1;
  fetchList();
}
function handleSearch() {
  pageNum.value = 1;
  fetchList();
}

// 弹窗
function openDialog(row) {
  if (row) {
    isCreate.value = false;
    dialogTitle.value = "编辑分类";
    Object.assign(form, row);
  } else {
    isCreate.value = true;
    dialogTitle.value = "新增分类";
    Object.assign(form, {
      id: null,
      parentId: null,
      name: "",
      description: "",
      sort: 0,
      status: 1,
      iconUrl: "",
    });
  }
  dialogVisible.value = true;
}

// 提交
function submitForm() {
  formRef.value.validate(async (valid) => {
    if (!valid) return;
    saving.value = true;
    try {
      if (isCreate.value) {
        await addCategory(form);
        ElMessage.success("新增成功");
      } else {
        await updateCategory(form);
        ElMessage.success("更新成功");
      }
      dialogVisible.value = false;
      fetchList();
    } finally {
      saving.value = false;
    }
  });
}

// 删除
function handleDelete(id) {
  ElMessageBox.confirm("确认删除？", "提示", { type: "warning" }).then(
    async () => {
      await deleteCategory(id);
      ElMessage.success("删除成功");
      fetchList();
    }
  );
}

// 批量删除
function handleBatchDelete() {
  ElMessageBox.confirm("确认删除选中分类？", "提示", { type: "warning" }).then(
    async () => {
      await Promise.all(multiple.value.map((i) => deleteCategory(i.id)));
      ElMessage.success("批量删除成功");
      multiple.value = [];
      fetchList();
    }
  );
}

// 状态切换
async function onChangeStatus(row) {
  await updateCategoryStatus(row.id, row.status);
  ElMessage.success("状态已更新");
}

// 排序修改
async function onChangeSort(row) {
  await updateCategorySort(row.id, row.sort);
  ElMessage.success("排序已更新");
}

// 导出
function handleExport() {
  exportCategories().then((res) => {
    const url = URL.createObjectURL(new Blob([res]));
    const a = document.createElement("a");
    a.href = url;
    a.download = "分类列表.xlsx";
    a.click();
    URL.revokeObjectURL(url);
  });
}

// 下载模板
function downloadTemplate() {
  downloadCategoryTemplate().then((res) => {
    const url = URL.createObjectURL(new Blob([res]));
    const a = document.createElement("a");
    a.href = url;
    a.download = "分类导入模板.xlsx";
    a.click();
    URL.revokeObjectURL(url);
  });
}

// 导入
function handleImport(file) {
  importCategories(file).then(() => {
    ElMessage.success("导入成功");
    fetchList();
  });
  return false;
}

onMounted(async () => {
  await loadTree();
  await fetchList();
});
</script>
  
<style scoped>
.categories-page {
  padding: 20px;
  border-radius: 18px;
  box-shadow: 0 6px 32px 0 rgba(80,120,200,0.08);
  min-height: 90vh;
  transition: box-shadow 0.3s;
}
.categories-page .toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 24px;
  align-items: center;
  background: rgba(255,255,255,0.85);
  border-radius: 14px;
  box-shadow: 0 2px 12px 0 rgba(80,120,200,0.06);
  padding: 18px 18px 10px 18px;
  animation: fadeInDown 0.7s;
}
@keyframes fadeInDown {
  from { opacity: 0; transform: translateY(-20px); }
  to { opacity: 1; transform: none; }
}
.toolbar-item {
  width: 200px;
  min-width: 120px;
  transition: box-shadow 0.2s, border-color 0.2s;
}
.toolbar-item .el-input__wrapper,
.toolbar-item .el-select__wrapper {
  border-radius: 8px;
  box-shadow: 0 1px 4px 0 rgba(80,120,200,0.04);
}
.toolbar-item .el-input__wrapper:hover,
.toolbar-item .el-select__wrapper:hover {
  border-color: #6c8cff;
  box-shadow: 0 2px 8px 0 rgba(80,120,200,0.10);
}
.el-button[type="primary"] {
  background: linear-gradient(90deg, #6c8cff 0%, #88e0ef 100%);
  border: none;
  color: #fff;
  font-weight: 500;
  box-shadow: 0 2px 8px 0 rgba(80,120,200,0.10);
  transition: background 0.2s, box-shadow 0.2s;
}
.el-button[type="primary"]:hover {
  background: linear-gradient(90deg, #88e0ef 0%, #6c8cff 100%);
  color: #fff;
}
.el-button[type="danger"] {
  background: linear-gradient(90deg, #ff6c6c 0%, #ffb88c 100%);
  border: none;
  color: #fff;
  font-weight: 500;
  box-shadow: 0 2px 8px 0 rgba(255,108,108,0.10);
  transition: background 0.2s, box-shadow 0.2s;
}
.el-button[type="danger"]:hover {
  background: linear-gradient(90deg, #ffb88c 0%, #ff6c6c 100%);
  color: #fff;
}
.action-btns {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 14px;
  min-width: 100px;
}
.el-table {
  border-radius: 14px;
  overflow: hidden;
  background: rgba(255,255,255,0.98);
  box-shadow: 0 2px 16px 0 rgba(80,120,200,0.07);
  animation: fadeIn 0.7s;
}
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}
.el-table th {
  background: linear-gradient(90deg, #f0f4ff 0%, #f8fafc 100%);
  color: #4a5a7a;
  font-weight: 600;
  font-size: 15px;
}
.el-table tr {
  transition: background 0.2s;
}
.el-table tr:hover {
  background: #eaf3ff !important;
}
.el-table .el-table__row.selected {
  background: #d6e4ff !important;
}
.el-table .el-button {
  border-radius: 50%;
  font-size: 18px;
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 2px;
  box-shadow: 0 1px 4px 0 rgba(80,120,200,0.08);
  transition: background 0.2s, transform 0.2s;
}
.el-table .el-button:hover {
  background: linear-gradient(90deg, #6c8cff 0%, #88e0ef 100%);
  color: #fff;
  transform: scale(1.12);
}
.pagination {
  text-align: center;
  margin-top: 24px;
}
.el-pagination {
  border-radius: 10px;
  background: rgba(255,255,255,0.85);
  box-shadow: 0 2px 8px 0 rgba(80,120,200,0.06);
  padding: 8px 16px;
}
.el-dialog {
  border-radius: 18px !important;
  box-shadow: 0 8px 40px 0 rgba(80,120,200,0.18) !important;
  animation: fadeInUp 0.5s;
}
@keyframes fadeInUp {
  from { opacity: 0; transform: translateY(40px); }
  to { opacity: 1; transform: none; }
}
.el-dialog__header {
  font-size: 22px;
  font-weight: 700;
  color: #3a4a6a;
  letter-spacing: 1px;
}
.el-dialog__footer {
  background: #f8fafc;
  border-radius: 0 0 18px 18px;
  padding: 18px 24px;
}
.el-form-item__label {
  font-weight: 600;
  color: #3a4a6a;
  font-size: 15px;
}
.el-form-item .el-input__wrapper,
.el-form-item .el-select__wrapper {
  border-radius: 8px;
  box-shadow: 0 1px 4px 0 rgba(80,120,200,0.04);
  transition: box-shadow 0.2s, border-color 0.2s;
}
.el-form-item .el-input__wrapper:focus-within,
.el-form-item .el-select__wrapper:focus-within {
  border-color: #6c8cff;
  box-shadow: 0 2px 8px 0 rgba(80,120,200,0.10);
}
/* 响应式 */
@media screen and (max-width: 1024px) {
  .categories-page {
    padding: 8px 2px 12px 2px;
  }
  .toolbar {
    flex-direction: column;
    gap: 10px;
    padding: 12px 8px 6px 8px;
  }
  .action-btns {
    min-width: 80px;
  }
  .el-table th, .el-table td {
    font-size: 13px;
  }
}
@media screen and (max-width: 768px) {
  .categories-page {
    padding: 2px 0 6px 0;
    min-height: unset;
  }
  .toolbar {
    flex-direction: column;
    gap: 8px;
    padding: 8px 2px 4px 2px;
  }
  .toolbar-item {
    min-width: 90px;
    width: 100%;
  }
  .el-table th, .el-table td {
    font-size: 12px;
    padding: 4px 2px;
  }
  .el-dialog {
    width: 98vw !important;
    min-width: unset;
    padding: 0;
  }
}
</style>
  